/*
	This is a part of the source code for Pro/DESKTOP.
	Copyright (C) 1998-1999 Parametric Technology Corporation.
	All rights reserved.
*/


// Demo spindle and wheel assembly file

#include <stdafx.h>

//Interface includes
#include "IApplication.h"
#include "IPartDocument.h"
#include "IGraphicDocument.h"
#include "IaWorkplane.h"
#include "IaSketch.h"
#include "IaLine.h"
#include "IzStraight.h"
#include "ISet.h"
#include "IzVector.h"
#include "IzPlane.h"
#include "IaGeometric.h"
#include "IaExtrusion.h"
#include "IHelm.h"

//Global Variables
IApplication *pdApp;

//==============================================================================================================
//Forward declarations of some convenience functions used by GearDesign()
HRESULT GetProDESKTOPApplication(IApplication **proDApp);
HRESULT GetActivePartWorkplaneSketch(IPartDocument **activePart, IGraphicDocument **activeGraphicDoc, IWorkplane **activeWorkplane, ISketch **activeSketch);
HRESULT CommitToProDESKTOP(CString str,BOOL bl = FALSE);
HRESULT AddComponent(CString strfileName, IDesign **component);
HRESULT AlignPlanes(IDesign *design, ITopology *pFirstTopology, ITopology *pSecondTopology, double offset, CString name);

//macro defintions
#define CHECK_RETURN_STATUS(status) \
	if (FAILED(status))
		return E_FAIL;

#define CAST(cls, obj) \
	QueryInterface<cls>(obj,IID_##cls) \

template <class T> 
T *QueryInterface(IDispatch *disp,GUID iid)
{
	void *pUnk;
	HRESULT status = disp->QueryInterface(iid,(void **)&pUnk);
	if (FAILED(status)) { 
		ASSERT(FALSE);
		AfxThrowOleException(status);
	} 
	disp->Release();
	return (T *)pUnk;

}

#define GetCLASS(cls) \
	GetFormalClass<I##cls##Class>(IID_I##cls##Class, #cls) \

template <class T>
T *GetFormalClass(GUID iid, CString clsName)
{
	IDispatch *disp = NULL;
	HRESULT status = pdApp->GetClass(clsName.AllocSysString(), &disp);

	T *thisCls = NULL;
	status = disp->QueryInterface(iid, (void **)&thisCls);
	if(status || !thisCls) {
		AfxMessageBox("QueryInterface Failed");
		return NULL;
	}
	return thisCls;
}

//==============================================================================================================

HRESULT DemoSpindleWheelAssembly() 
{
	HRESULT status = CONV_SUCCESS ;

	IApplication *pdApplication = NULL ;
	IGraphicDocument *activeGraphicDoc = NULL;
	IPartDocument * activePart = NULL;
	IWorkplane * activeWorkplane = NULL;
	ISketch * activeSketch = NULL;

	// Get the application
	status = GetProDESKTOPApplication(&pdApplication) ;
	CHECK_RETURN_STATUS(status)
	pdApp = pdApplication;

	AfxMessageBox("Creating Spindle") ;

	CString comp1 = "..\\spindle.des" ;
	CString comp2 = "..\\wheel.des" ;

	status = Spindle(comp1, TRUE);

	if (status) {
		AfxMessageBox("DrawSpindle failed");
		return CONV_FAILURE;
	}

	AfxMessageBox(" Creating Wheel ") ;

	status = Wheel(comp2, TRUE) ;
	if (status) {
		AfxMessageBox("DrawWheel failed");
		return CONV_FAILURE;
	}

	AfxMessageBox(" Making Assembly ") ;
	IPartDocument *pdisp = NULL ;
	
	status = pdApplication->NewPart(&pdisp);
	if (status || !pdisp) {
		AfxMessageBox("Could not create new part");
		return CONV_FAILURE;
	}

	IDesign *pDesign1 = NULL, *pDesign2 = NULL;
	status = AddComponent(comp1, &pDesign1) ;
	if (status) {
		AfxMessageBox("AddComponent failed");
		return CONV_FAILURE;
	}

	status = CommitToProDESKTOP("AddComponent");
	CHECK_RETURN_STATUS(status)

	status = AddComponent(comp2,&pDesign1) ;
	if (status) {
		AfxMessageBox("AddComponent failed");
		return CONV_FAILURE;
	}

	status = CommitToProDESKTOP("UpdateDesign");
	CHECK_RETURN_STATUS(status)

	//To Center the axes of the wheel and spindle
	AfxMessageBox("Select one circular edge of the wheel and one circular edge of the spindle");

	status = CommitToProDESKTOP("Selection", TRUE);
	CHECK_RETURN_STATUS(status)

	ISet *pselectionset = NULL;

	status = activeGraphicDoc->GetSelection(GetBSTR("Edge" ), &pselectionset);
	CHECK_RETURN_STATUS(status)

	IIt *pObjectIt = NULL;
	status = GetClass("It")->CreateAObjectIt(pselectionset, &pObjectIt);
	CHECK_RETURN_STATUS(status);

	IDispatch *pDispObject = NULL;
	ITopology *pFirstTopology = NULL;
	ITopology *pSecondTopology = NULL;

	status = pObjectIt->Start(&pDispObject);
	CHECK_RETURN_STATUS(status)
	pFirstTopology = CAST(ITopology, pDispObject);

	status = pObjectIt->Next(&pDispObject);
	CHECK_RETURN_STATUS(status)
	pSecondTopology = CAST(ITopology, pDispObject);

	status = CenterAxes(pFirstTopology, pSecondTopology);
	CHECK_RETURN_STATUS(status)

	status = CommitToProDESKTOP("Center Axes");
	CHECK_RETURN_STATUS(status)

	//To Align the Spindle and the Wheel
	AfxMessageBox("Select one planar face of the Wheel and one planar face of the spindle");

	status = CommitToProDESKTOP("Align Planes", TRUE);
	CHECK_RETURN_STATUS(status)

	ISet *pSelectionSet = NULL;

	status = activeGraphicDoc->GetSelection(GetBSTR("Topology"), &pSelectionSet);
	CHECK_RETURN_STATUS(status)

	IIt *pObjectIt = NULL;
	status = GetClass("It")->CreateAObjectIt(pSelectionSet, &pObjectIt);
	CHECK_RETURN_STATUS(status)

	IDispatch *pDispObject = NULL;
	ITopology *pFirstTopology = NULL;
	ITopology *pSecondTopology = NULL;

	status = pObjectIt->Start(&pDispObject);
	CHECK_RETURN_STATUS(status)
	pFirstTopology = CAST(ITopology, pDispObject);

	status = pObjectIt->Next(&pDispObject);
	CHECK_RETURN_STATUS(status)
	pSecondTopology = CAST(ITopology, pDispObject);

	IDesign *pDesign;
	status = activePart->GetDesign(&pDesign);
	CHECK_RETURN_STATUS(status);

	double offset = 0.0;
	CString name;
	name.Format("DemoAlign %d", ++alignCount);
	
	status = AlignPlanes(pDesign, pFirstTopology, pSecondTopology, offset, name);
	CHECK_RETURN_STATUS(status)

	status = CommitToProDESKTOP("Align Planes");
	CHECK_RETURN_STATUS(status)

	return NOERROR;
}

HRESULT Spindle(CString filename, BOOL saveFlag) 
{
	HRESULT status = CONV_SUCCESS;

	IApplication *pdApplication = NULL ;
	IGraphicDocument *activeGraphicDoc = NULL;
	IPartDocument * activePart = NULL;
	IWorkplane * activeWorkplane = NULL;
	ISketch * activeSketch = NULL;
	IGeometric *localGeometric = NULL;
	IPlane *localZPlane = NULL;
	
	// Get the application
	status = GetProDESKTOPApplication(&pdApplication) ;
	CHECK_VAR_STATUS(pdApplication)

	IPartDocument *pDisp = NULL;
	status = pdApplication->NewPart(&pDisp);
	status = GetActivePartWorkplaneSketch(&activePart, &activeGraphicDoc, &activeWorkplane, &activeSketch);
	CHECK_RETURN_STATUS(status)

	IVector *pVector1 = NULL;
	status = GetClass("Vector")->CreateVector(-0.15, 0.02, 0, &pVector1);

	IVector *pVector2 = NULL;
	status = GetClass("Vector")->CreateVector(-0.15, 0.0375, 0, &pVector2);

	IVector *pVector3 = NULL;
	status = GetClass("Vector")->CreateVector(-0.07915, 0.0375, 0, &pVector3);

	IVector *pVector4 = NULL;
	status = GetClass("Vector")->CreateVector(-0.07915, 0.0625, 0, &pVector4);

	IVector *pVector5 = NULL;
	status = GetClass("Vector")->CreateVector(0.07915, 0.0625, 0, &pVector5);

	IVector *pVector6 = NULL;
	status = GetClass("Vector")->CreateVector(0.07915, 0.0375, 0, &pVector6);

	IVector *pVector7 = NULL;
	status = GetClass("Vector")->CreateVector(0.15, 0.0375, 0, &pVector7);

	IVector *pVector8 = NULL;
	status = GetClass("Vector")->CreateVector(0.15, 0.02, 0, &pVector8);

	localGeometric = CAST(IGeometric, activeWorkplane);

	IGeometry *pGeom1 = NULL;
	status = localGeometric->GetGeometry (&pGeom1);
	localZPlane = CAST(IPlane, pGeom1);

	IDirection *pNormal1 = NULL;
	status = localZPlane->GetNormal(&pNormal1);

	ILine *pLine1 = NULL, *pLine2 = NULL, *pLine3 = NULL, *pLine4 = NULL, *pLine5 = NULL, *pLine6 = NULL, *pLine7 = NULL, *pLine8 = NULL;

	IBasicStraight *curve1 = NULL;
    status = GetClass("BasicStraight")->CreateBasicStraightTwoPoints(pVector1,pVector2,&curve1);
	status = activeSketch->CreateLine(CAST(ICurve, curve1), &pLine1);

	IBasicStraight *curve2 = NULL;
    status = appZObject -> CreateBasicStraightTwoPoints(pVector2,pVector3,&curve2);
	status = activeSketch->CreateLine(CAST(ICurve, curve2), &pLine2);

	IBasicStraight *curve3 = NULL;
    status = GetClass("BasicStraight")->CreateBasicStraightTwoPoints(pVector3,pVector4,&curve3);
	status = activeSketch->CreateLine(CAST(ICurve, curve3), &pLine3);

	IBasicStraight *curve4 = NULL;
    status = GetClass("BasicStraight")->CreateBasicStraightTwoPoints(pVector4,pVector5,&curve4);
	status = activeSketch->CreateLine(CAST(ICurve, curve4), &pLine4);

	IBasicStraight *curve5 = NULL;
    status = GetClass("BasicStraight")->CreateBasicStraightTwoPoints(pVector5,pVector6,&curve5);
	status = activeSketch->CreateLine(CAST(ICurve, curve5), &pLine5);

	IBasicStraight *curve6 = NULL;
    status = GetClass("BasicStraight")->CreateBasicStraightTwoPoints(pVector6,pVector7,&curve6);
	status = activeSketch->CreateLine(CAST(ICurve, curve6), &pLine6);

	IBasicStraight *curve7 = NULL;
    status = GetClass("BasicStraight")->CreateBasicStraightTwoPoints(pVector7,pVector8,&curve7);
	status = activeSketch->CreateLine(CAST(ICurve, curve7), &pLine7);

	IBasicStraight *curve8 = NULL;
    status = GetClass("BasicStraight")->CreateBasicStraightTwoPoints(pVector8,pVector1,&curve8);
	status = activeSketch->CreateLine(CAST(ICurve, curve8), &pLine8);

	// Get active workplane

	status = activeGraphicDoc->GetActiveWorkplane(&activeWorkplane);
	CHECK_RETURN_STATUS(status)

	ISketch *initialSketch = NULL;
	status = activeGraphicDoc->GetActiveSketch(&initialSketch);

	// create new  sketch
	ISketch *pSketch = NULL;
	CString strSketch = "Sketch1";
	status = activeWorkplane->CreateSketch(strSketch.AllocSysString(),&pSketch);
	status = activeGraphicDoc->SetActiveSketch(pSketch) ;

	// create Axis ....
	IRevolution *pRev=NULL;
	IDesign *pDesign = NULL;

	localGeometric = CAST(IGeometric, activeWorkplane);

	IGeometry *pGeom2 = NULL;
	status = localGeometric->GetGeometry (&pGeom2);
	localZPlane = CAST(IPlane, pGeom2);

	IDirection *pNormal2 = NULL;
	status = localZPlane->GetNormal(&pNormal2);

	IVector *pStart = NULL;
 	GetClass("Vector")->CreateVector(-0.1, 0, 0, &pStart);

	IVector *pEnd = NULL;
	GetClass("Vector")->CreateVector(0.1, 0, 0, &pEnd);

	IBasicStraight *curve9 = NULL;
	status = GetCLASS("BasicStraight")->CreateBasicStraightTwoPoints(pStart,pEnd,&curve9);
	ILine *pAxis = NULL;
	status = pSketch->CreateLine(CAST(ICurve, curve9), &pAxis);

	// revolution ....
	status = activePart->GetDesign(&pDesign);
	GetClass("Revolution")->CreateRevolution(pDesign,initialSketch,pSketch,6.28,0,0,TRUE,&pRev) ;

	status = CommitToProDESKTOP("Revolution");
	CHECK_RETURN_STATUS(status)

	activePart->UpdateDesign();
	
	status = CommitToProDESKTOP("UpdateDesign");
	CHECK_RETURN_STATUS(status)

	if (saveFlag) {
	VARIANT_BOOL retVal;
	status = activeGraphicDoc->Close(filename.AllocSysString(), TRUE, &retVal) ;
	CHECK_RETURN_STATUS(status)
	}

	return NOERROR;
}

HRESULT Wheel(CString filename, BOOL saveFlag) 
{
	HRESULT status = CONV_SUCCESS;

	IApplication *pdApplication = NULL ;
	IGraphicDocument *activeGraphicDoc = NULL;
	IPartDocument * activePart = NULL;
	IWorkplane * activeWorkplane = NULL;
	ISketch * activeSketch = NULL;
	IPlane *localZPlane = NULL;
	IGeometric *localGeometric = NULL;
	
	// Get the application
	status = GetProDESKTOPApplication(&pdApplication) ;
	CHECK_RETURN_STATUS(status)

	IPartDocument *pDisp = NULL;
	status = pdApplication->NewPart(&pDisp);

	status = GetActivePartWorkplaneSketch(&activePart, &activeGraphicDoc, &activeWorkplane, &activeSketch);
	CHECK_RETURN_STATUS(status)

	IVector *pVector1 = NULL;
	GetClass("Vector")->CreateVector(-0.07915, 0.0625, 0, &pVector1);

	IVector *pVector2 = NULL;
	GetClass("Vector")->CreateVector(-0.07915, 0.0815,0, &pVector2);

	IVector *pVector3 = NULL;
	GetClass("Vector")->CreateVector(-0.0125, 0.105, 0, &pVector3);

	IVector *pVector4 = NULL;
	GetClass("Vector")->CreateVector(-0.0125, 0.155, 0, &pVector4);

	IVector *pVector5 = NULL;
	GetClass("Vector")->CreateVector(-0.069, 0.1725, 0, &pVector5);

	IVector *pVector6 = NULL;
	GetClass("Vector")->CreateVector(-0.069, 0.1875, 0, &pVector6);

	IVector *pVector7 = NULL;
	GetClass("Vector")->CreateVector(0.069, 0.1875, 0, &pVector7);

	IVector *pVector8 = NULL;
	GetClass("Vector")->CreateVector(0.069, 0.1725, 0, &pVector8);

	IVector *pVector9 = NULL;
	GetClass("Vector")->CreateVector(0.0125, 0.155, 0, &pVector9);

	IVector *pVector10 = NULL;
	GetClass("Vector")->CreateVector(0.0125, 0.105, 0, &pVector10);

	IVector *pVector11 = NULL;
	GetClass("Vector")->CreateVector(0.07915, 0.0815, 0, &pVector11);

	IVector *pVector12 = NULL;
	GetClass(""Vector)->CreateVector(0.07915, 0.0625, 0, &pVector12);

	localGeometric = CAST(IGeometric, activeWorkplane);

	IGeometry *pGeom = NULL;
	status = localGeometric->GetGeometry (&pGeom);
	
	localZPlane = CAST(IPlane, pGeom);
	IDirection *pNormal1 = NULL;
	status = localZPlane->GetNormal(&pNormal1);

	ILine *pLine1 = NULL, *pLine2 = NULL, *pLine3 = NULL, *pLine4 = NULL, *pLine5 = NULL, *pLine6 = NULL, *pLine7 = NULL, *pLine8 = NULL, *pLine9 = NULL, *pLine10 = NULL, *pLine11 = NULL, *pLine12 = NULL;
	IBasicStraight *curve1 = NULL;
    status = appZObject -> CreateBasicStraightTwoPoints(pVector1,pVector2,&curve1);
	status = activeSketch->CreateLine(CAST(ICurve, curve1), &pLine1);

	IBasicStraight *curve2 = NULL;
    status = appZObject -> CreateBasicStraightTwoPoints(pVector2,pVector3,&curve2);
	status = activeSketch->CreateLine(CAST(ICurve, curve2), &pLine2);

	IBasicStraight *curve3 = NULL;
    status = appZObject -> CreateBasicStraightTwoPoints(pVector3,pVector4,&curve3);
	status = activeSketch->CreateLine(CAST(ICurve, curve3), &pLine3);

	IBasicStraight *curve4 = NULL ;
    status = appZObject -> CreateBasicStraightTwoPoints(pVector4,pVector5,&curve4);
	status = activeSketch->CreateLine(CAST(ICurve, curve4), &pLine4);

	IBasicStraight *curve5 = NULL;
    status = appZObject -> CreateBasicStraightTwoPoints(pVector5,pVector6,&curve5);
	status = activeSketch->CreateLine(CAST(ICurve, curve5), &pLine5);

	IBasicStraight *curve6 = NULL;
    status = appZObject -> CreateBasicStraightTwoPoints(pVector6,pVector7,&curve6);
	status = activeSketch->CreateLine(CAST(ICurve, curve6), &pLine6);

	IBasicStraight *curve7 = NULL;
    status = appZObject -> CreateBasicStraightTwoPoints(pVector7,pVector8,&curve7);
	status = activeSketch->CreateLine(CAST(ICurve, curve7), &pLine7);

	IBasicStraight *curve8 = NULL;
    status = appZObject -> CreateBasicStraightTwoPoints(pVector8,pVector9,&curve8);
	status = activeSketch->CreateLine(CAST(ICurve, curve8), &pLine8);

	IBasicStraight *curve9 = NULL;
    status = appZObject -> CreateBasicStraightTwoPoints(pVector9,pVector10,&curve9);
	status = activeSketch->CreateLine(CAST(ICurve, curve9), &pLine9);

	IBasicStraight *curve10 = NULL;
    status = appZObject -> CreateBasicStraightTwoPoints(pVector10,pVector11,&curve10);
	status = activeSketch->CreateLine(CAST(ICurve, curve10), &pLine10);

	IBasicStraight *curve11 = NULL;
    status = appZObject -> CreateBasicStraightTwoPoints(pVector11,pVector12,&curve11);
	status = activeSketch->CreateLine(CAST(ICurve, curve11), &pLine11);

	IBasicStraight *curve12 = NULL;
    status = appZObject -> CreateBasicStraightTwoPoints(pVector12,pVector1,&curve12);
	status = activeSketch->CreateLine(CAST(ICurve, curve12), &pLine12);

	// Get active workplane
	status = activeGraphicDoc->GetActiveWorkplane(&activeWorkplane);
	CHECK_RETURN_STATUS(status)

	ISketch *initialSketch = NULL;
	status = activeGraphicDoc->GetActiveSketch(&initialSketch);

	// create new  sketch
	ISketch *pSketch = NULL;
	CString strSketch = "Sketch1";
	status = activeWorkplane->CreateSketch(strSketch.AllocSysString(),&pSketch);
	status = activeGraphicDoc->SetActiveSketch(pSketch) ;

	// create Axis ....
	IRevolution *pRev=NULL;
	IDesign *pDesign = NULL;

	localGeometric = CAST(IGeometric, activeWorkplane);
	IGeometry *pGeom2 = NULL;
	status = localGeometric->GetGeometry (&pGeom2);
	localZPlane = CAST(IPlane, pGeom2);

	IDirection *pNormal= NULL;
	status = localZPlane->GetNormal(&pNormal);

	IVector *pStart = NULL;
 	status = GetClass("Vector")->CreateVector(-0.1, 0, 0, &pStart);

	IVector *pEnd = NULL;
	status = GetClass("Vector")->CreateVector(0.1, 0, 0, &pEnd);

	IBasicStraight *curve13 = NULL;
	ILine *pLine13 = NULL;
    status = GetCLASS("BasicStraight")->CreateBasicStraightTwoPoints(pStart,pEnd,&curve13);
	status = pSketch->CreateLine(CAST(ICurve, curve13), &pLine13);

	// revolution ....
	status = activePart->GetDesign(&pDesign);
	status = GetClass("Revolution")->CreateRevolution(pDesign,initialSketch,pSketch,6.28,0,0,TRUE,&pRev) ;

	status = CommitToProDESKTOP("Revolution");
	CHECK_RETURN_STATUS(status)

	activePart->UpdateDesign();

	status = CommitToProDESKTOP("UpdateDesign");
	CHECK_RETURN_STATUS(status)

	if (saveFlag) {
	VARIANT_BOOL retVal;
	status = activeGraphicDoc->Close(filename.AllocSysString(), TRUE, &retVal) ;
	CHECK_RETURN_STATUS(status)
	}

	return NOERROR;
}

//===========================================================================================================

HRESULT GetProDESKTOPApplication(IApplication **proDApp)
{
	HRESULT status = NOERROR;
	IApplication *app = NULL;

	if (pdApp = NULL) {
		status = CoCreateInstance(CLSID_ProDESKTOP, NULL, CLSCTX_SERVER, IID_IApplication, (void**)&app);
		CHECK_RETURN_STATUS(status)

		status = (app)->SetVisible(TRUE);
		CHECK_RETURN_STATUS(status)
		*proDApp = app;
	}
	else 
		proDApp = pdApp;

	return NOERROR;
}

HRESULT GetActivePartWorkplaneSketch(IPartDocument **activePart,
									 IGraphicDocument **activeGraphicDoc,
									 IWorkplane **activeWorkplane,
									 ISketch **activeSketch)
{
/* Queries the  PartDocument, Workplane , and Sketch Interfaces and returns the active Part, active Workplane, active Sketch. */

	HRESULT status = NOERROR;

	IPartDocument *part = NULL;
	IWorkplane *workplane = NULL;

	ISketch * sketch = NULL;
	IApplication *app = NULL;

	// Get the application
	status = GetProDESKTOPApplication(&app) ;
	CHECK_RETURN_STATUS(status)

	status = app->GetActiveDoc(activeGraphicDoc);
	CHECK_RETURN_STATUS(status)

	*activePart = CAST(IPartDocument, *activeGraphicDoc);

	// Get active workplane
	status = (*activeGraphicDoc)->GetActiveWorkplane(activeWorkplane);
	CHECK_RETURN_STATUS(status)

	// Get active sketch
	status = (*activeGraphicDoc)->GetActiveSketch(activeSketch);
	CHECK_RETURN_STATUS(status)

	return NOERROR;
}

HRESULT CommitToProDESKTOP(CString str,BOOL bl)
{
	HRESULT status = CONV_SUCCESS;

	// Take the helm
	IHelm *pHelm = NULL;
	status = GetProDESKTOPApplication(&app);
	CHECK_RETURN_STATUS(status)

	status = app->TakeHelm(&pHelm);
	CHECK_RETURN_STATUS(status)

	// Committing the operation
	status = pHelm->CommitCalls(str.AllocSysString(), bl);
	CHECK_RETURN_STATUS(status)

	pHelm->Release();

	return NOERROR;
}

HRESULT AddComponent(CString strfileName, IDesign **component)
{
	HRESULT status = CONV_SUCCESS;
	IDispatch *pDisp = NULL;
	
	long count;
	BSTR str;

	IGraphicDocument *activeGraphicDoc = NULL;
	IPartDocument *activePart = NULL;
	IWorkplane *activeWorkplane = NULL;
	ISketch *activeSketch = NULL;

	status = GetActivePartWorkplaneSketch(&activePart, &activeGraphicDoc, &activeWorkplane, &activeSketch);
	CHECK_RETURN_STATUS(status)

	IDesign *design = NULL;
	status = activePart->OpenDesign(strfileName.AllocSysString(),&design);
	CHECK_RETURN_STATUS(status)
	
	IVector *pLocalOrigin = NULL;

	// get the origin
	status = activeWorkplane->GetLocalOrigin(&pLocalOrigin);
	CHECK_RETURN_STATUS(status)

	IDirection *pLocalX = NULL;
	status = activeWorkplane->GetLocalX(&pLocalX);
	CHECK_RETURN_STATUS(status)

	IDirection *pLocalY = NULL;
	status = activeWorkplane->GetLocalY(&pLocalY);
	CHECK_RETURN_STATUS(status)

	IMatrix *pTemp1 = NULL;
	status = GetClass("Matrix")->CreateTranslationMatrix(pLocalOrigin, &pTemp1);
	CHECK_RETURN_STATUS(status)

	IMatrix *pTemp2 = NULL;
	status = GetClass("Matrix")->CreateRotationMatrix(pLocalX, pLocalY, &pTemp2);
	CHECK_RETURN_STATUS(status)

	// multiply the matrix
	IMatrix *pTranslation = NULL;
	status = pTemp1->MultiplyByMatrix(pTemp2, &pTranslation);
	CHECK_RETURN_STATUS(status)

	ISet *workplaneSet = NULL;
	status = design->GetWorkplanes(&workplaneSet);
	CHECK_RETURN_STATUS(status)

	status = workplaneSet->GetCount(&count);
	CHECK_RETURN_STATUS(status)

	IDispatch *pCurrentWorkplane = NULL;
	IWorkplane *currentWorkplane = NULL;

	IIt *pObjectIt = NULL;
	status = GetClass("It")->CreateAObjectIt(workplaneSet, &pObjectIt);
	CHECK_RETURN_STATUS(status)

	// loop to get base workplane
	status = pObjectIt->Start(&pCurrentWorkplane);
    while (pCurrentWorkplane) {
		currentWorkplane = CAST(IWorkplane, pCurrentWorkplane);

        status = currentWorkplane->GetName(&str);
		CHECK_RETURN_STATUS(status)
		CString str1(str);

		IVector *pCurrrentOrigin = NULL;

		// if current work plane is base one
		if (strcmp(str1,"base") == 0){
			status = currentWorkplane->GetLocalOrigin(&pCurrrentOrigin);
			CHECK_RETURN_STATUS(status)
			
			IDirection *pCurrentX = NULL;
			IDirection *pCurrentY = NULL;

			status = currentWorkplane->GetLocalX(&pCurrentX);
			CHECK_RETURN_STATUS(status)

			status = currentWorkplane->GetLocalY(&pCurrentY);
			CHECK_RETURN_STATUS(status)

			IMatrix *matrix = NULL;
            status = GetClass("Matrix")->CreateTranslationMatrix(pCurrrentOrigin, &matrix);
			CHECK_RETURN_STATUS(status)

			IMatrix *pTemp4 = NULL;
            status = GetClass("Matrix")->CreateRotationMatrix(pCurrentX, pCurrentY, &pTemp4);
			CHECK_RETURN_STATUS(status)

			IMatrix *pOldMapping = NULL;

			status = matrix->MultiplyByMatrix(pTemp4, &pOldMapping);
			CHECK_RETURN_STATUS(status)

			IMatrix *pInverse = NULL;
			// find inverse
			status = pOldMapping->GetInverse(&pInverse);
			CHECK_RETURN_STATUS(status)

			// multiply matrix
			IMatrix *matrix2 = NULL;
			status = pTranslation->MultiplyByMatrix(pInverse, &matrix2);
			CHECK_RETURN_STATUS(status)

            break;
		}
		pCurrentWorkplane = NULL;
			pObjectIt->Next(&pCurrentWorkplane);

    }

	IDesign *design1= NULL;
	// get the design component
	status = activePart->GetDesign(&design1);
	CHECK_RETURN_STATUS(status)

	// Create component
	IDesign *comp = NULL;
    status = design1->CreateComponent(design, pTranslation, &comp);
	CHECK_RETURN_STATUS(status)
	*component = comp;

	return NOERROR;
}

HRESULT AlignPlanes(IDesign *design, ITopology *pFirstTopology, ITopology *pSecondTopology, double offset, CString name)
{
	HRESULT status = CONV_SUCCESS;

	VARIANT_BOOL bVal;
	IApplication *pdApplication = NULL;

	// Get the application
	status = GetProDESKTOPApplication(&pdApplication) ;
	CHECK_RETURN_STATUS(status)

	IGraphicDocument *activeGraphicDoc = NULL;
	IPartDocument *activePart = NULL;
	IWorkplane *activeWorkplane = NULL;
	ISketch *activeSketch = NULL;

	status = GetActivePartWorkplaneSketch(&activePart, &activeGraphicDoc, &activeWorkplane, &activeSketch);
	CHECK_RETURN_STATUS(status)

	IObject *object1 = NULL;
	IObject *object2 = NULL;

	VARIANT_BOOL blnFirstTopology;
	VARIANT_BOOL blnSecondTopology;

	// check for first topology
	CHECK_VAR_STATUS(pFirstTopology)

	object1 = CAST(IObject, pFirstTopology);
	status = object1->IsA(GetBSTR("Topology"),&blnFirstTopology);
	CHECK_RETURN_STATUS(status)

	// check for second topology
	CHECK_VAR_STATUS(pSecondTopology)
	
	object2 = CAST(IObject, pSecondTopology);

	status = object2->IsA(GetBSTR("Topology"),&blnSecondTopology);
	CHECK_RETURN_STATUS(status)

	IGraphicDocument *pActiveDoc = NULL;

	// if both the topologyclass is not NULL
	CHECK_VAR_STATUS(blnFirstTopology);
	CHECK_VAR_STATUS(blnSecondTopology);

	status = pdApplication->GetActiveDoc(&pActiveDoc);
	CHECK_RETURN_STATUS(status)
	
	IGeometric *geometric=NULL;

	geometric = CAST(IGeometric, pSecondTopology);

	ITopology *pTemp = NULL;

	// UpdateDependencies method
	if (geometric->IsDependentOn(CAST(IGeometric,pFirstTopology),&bVal)) {
		pTemp = pFirstTopology;
		pFirstTopology = pSecondTopology;
		pSecondTopology = pTemp;
	}

	IObject *pIns = NULL;
	status = object1->GetParent(GetBSTR("DesignInstance"),&pIns);
	CHECK_RETURN_STATUS(status)

	IAbutPlanes *pMatingCondition = NULL;
	
	VARIANT_BOOL reversed = FALSE;
	status = GetClass("Abut")->CreateAbutPlanes(design, CAST(IFace, pFirstTopology), CAST(IFace, pSecondTopology), offset, reversed, name.AllocSysString(), &pMatingCondition);
	CHECK_RETURN_STATUS(status)

	IDesignInstance *ins = CAST(IDesignInstance, pIns);

	status = ins->AddMatingCondition(CAST(IMatingCondition,pMatingCondition));
	CHECK_RETURN_STATUS(status)

	return NOERROR;
}

HRESULT CenterAxes(ITopology *pFirstTopology, ITopology *pSecondTopology)
{
	HRESULT status=CONV_SUCCESS;
	VARIANT_BOOL bVal;
	
	IDesignInstance *ins = NULL;
	IApplication *pdApplication = NULL;

	// Get the application
	status = GetProDESKTOPApplication(&pdApplication);
	CHECK_RETURN_STATUS(status)

	IGraphicDocument *activeGraphicDoc = NULL;
	IPartDocument *activePart = NULL;
	IWorkplane *activeWorkplane = NULL;
	ISketch *activeSketch = NULL;

	status = GetActivePartWorkplaneSketch(&activePart, &activeGraphicDoc, &activeWorkplane, &activeSketch);
	CHECK_RETURN_STATUS(status)

	IGraphicDocument *pActiveDoc = NULL;
	status = pdApplication->GetActiveDoc(&pActiveDoc);
	CHECK_RETURN_STATUS(status)

	ITopology *pTemp = NULL;
	IGeometric *geometric = CAST(IGeometric, pSecondTopology);

	// UpdateDependencies method
	status = geometric->IsDependentOn(CAST(IGeometric,pFirstTopology),&bVal);
	if (bVal) {
		pTemp = pFirstTopology;
		pFirstTopology = pSecondTopology;
		pSecondTopology = pTemp;
	}
	
	IObject *pIns = NULL;
	status = CAST(IObject, pFirstTopology)->GetParent(GetBSTR("DesignInstance"),&pIns);
	CHECK_RETURN_STATUS(status)

	ICenterAxes *pMatingCondition = NULL;

	status = GetClass("CenterAxes")->CreateCenterAxes(pFirstTopology, pSecondTopology, &pMatingCondition);
	CHECK_RETURN_STATUS(status)
 		
	ins = CAST(IDesignInstance, pIns);		
	status = ins->AddMatingCondition(CAST(IMatingCondition, pMatingCondition));
	CHECK_RETURN_STATUS(status)

	return NOERROR;
}
